package com.shockweb.register.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.shockweb.bridge.HostInfo;
import com.shockweb.bridge.ServerInfo;
import com.shockweb.bridge.Service;
import com.shockweb.bridge.ServiceHost;
import com.shockweb.bridge.ServiceSpace;
import com.shockweb.common.log.LogManager;

/**
 * 注册服务器的所有服务保存的地方
 * 
 * @author 彭明华
 * 2018年1月3日 创建
 */
public class ServiceRoot{
	


	/**
	 * 服务空间
	 */
	private Map<String,ServiceSpace> serviceSpaces = new HashMap<String,ServiceSpace>();
	
	/**
	 * 获取服务空间
	 * @param spaceName
	 * @return
	 */
	public ServiceSpace getServiceSpace(String spaceName){
		return serviceSpaces.get(spaceName);
	}

	
	/**
	 * 设置服务空间
	 * @param spaceName
	 * @param serviceSpace
	 */
	public void putServiceHost(String spaceName,ServiceSpace serviceSpace){
		serviceSpaces.put(spaceName,serviceSpace);
	}
	
	/**
	 * 删除服务空间
	 * @param spaceName
	 */
	public void removeServiceHost(String spaceName){
		serviceSpaces.remove(spaceName);
	}
	
	/**
	 * 根服务
	 */
	private static ServiceRoot serviceRoot = new ServiceRoot();
	
	/**
	 * 获取根服务
	 * @return
	 */
	public static ServiceRoot getServiceRoot(){
		synchronized(serviceRoot){
			return serviceRoot;
		}
	}
	
	/**
	 * 返回服务的定义
	 * @return
	 */
	public Map<String,ServiceSpace> getServiceSpaces(){
		synchronized(serviceRoot){
			Map<String,ServiceSpace> rtn = new HashMap<String,ServiceSpace>();
			Iterator<Entry<String,ServiceSpace>> its = serviceSpaces.entrySet().iterator();
			while(its.hasNext()){
				Entry<String,ServiceSpace> entry = its.next();
				ServiceSpace serviceSpace = new ServiceSpace();
				serviceSpace.setName(entry.getValue().getName());
				Iterator<Entry<String,Service>> serviceIts = entry.getValue().getServices().entrySet().iterator();
				while(serviceIts.hasNext()){
					Entry<String,Service> serviceEntry = serviceIts.next();
					Service service = new Service();
					service.setServiceName(serviceEntry.getValue().getServiceName());
					List<String> serviceHosts = new ArrayList<String>();
					for(String host:serviceEntry.getValue().getServiceHosts()){
						serviceHosts.add(host);
					}
					service.setServiceHosts(serviceHosts);
					serviceSpace.putService(service.getServiceName(), service);
				}
				Iterator<Entry<String,ServiceHost>> hostIts = entry.getValue().getServiceHosts().entrySet().iterator();
				while(hostIts.hasNext()){
					Entry<String,ServiceHost> hostEntry = hostIts.next();
					ServiceHost serviceHost = new ServiceHost();
					serviceHost.setHost(hostEntry.getValue().getHost());
					serviceHost.setCalled(hostEntry.getValue().getCalled());
					serviceHost.setTimeOut(hostEntry.getValue().getTimeOut());
					serviceHost.setDoing(hostEntry.getValue().getDoing());
					serviceHost.setSleepTime(hostEntry.getValue().getSleepTime());
					serviceHost.setThreshold(hostEntry.getValue().getThreshold());
					serviceHost.setUpdateTime(System.currentTimeMillis());
					serviceSpace.putServiceHost(serviceHost.getHost(), serviceHost);
				}
				rtn.put(serviceSpace.getName(), serviceSpace);
			}
			return rtn;
		}
	}
    
    

    
    /**
     * 清除服务定义
     */
    public void clear(){
		synchronized(serviceRoot){
			this.serviceSpaces.clear();
		}
    }
    
    /**
     * 刷新清理无效的服务
     */
    public void refresh(long activeTime) {
		synchronized(serviceRoot){
			Iterator<Entry<String,ServiceSpace>> it = serviceSpaces.entrySet().iterator();
			List<String> spaces = new ArrayList<String>();
			while(it.hasNext()){
				Entry<String,ServiceSpace> entry = it.next();
				if(entry!=null){
					ServiceSpace serviceSpace = entry.getValue();
					//清理过期的主机
					List<String> hosts = new ArrayList<String>();
					Map<String,ServiceHost> serviceHosts = serviceSpace.getServiceHosts();
					Iterator<Entry<String,ServiceHost>> hostIt = serviceHosts.entrySet().iterator();
					while(hostIt.hasNext()){
						Entry<String,ServiceHost> hostEntry = hostIt.next();
						if(hostEntry!=null){
							ServiceHost serviceHost = hostEntry.getValue();
							if(serviceHost.getUpdateTime()+activeTime<System.currentTimeMillis()){
								hosts.add(serviceHost.getHost());
								LogManager.warn(this.getClass(), "微服务'" + serviceHost.getHost() + "'失去心跳信息，最后状态为：" + serviceHost);
							}
						}
					}
					for(String host:hosts){
						serviceSpace.removeServiceHost(host);
					}
					//清理服务对应的主机
					Map<String,Service> service = serviceSpace.getServices();
					Iterator<Entry<String,Service>> serviceIt = service.entrySet().iterator();
					List<String> serviceNames = new ArrayList<String>();
					while(serviceIt.hasNext()){
						Entry<String,Service> serviceEntry = serviceIt.next();
						if(serviceEntry!=null){
							Service svc = serviceEntry.getValue();
							List<String> svcHosts = svc.getServiceHosts();
							for(String host:hosts){
								svcHosts.remove(host);
							}
							if(svcHosts.isEmpty()){
								serviceNames.add(svc.getServiceName());
							}
						}
					}
					//清理没有主机的服务
					for(String name:serviceNames){
						service.remove(name);
					}
					if(service.isEmpty()){
						spaces.add(serviceSpace.getName());
					}
				}
			}
			//清理没有服务的命名空间
			for(String name:spaces){
				serviceSpaces.remove(name);
			}
		}
    }
    
    /**
     * 将HostInfo更新到注册服务器中
     * @param info
     */
	public void putHostInfo(HostInfo info) {
		synchronized(serviceRoot){
			Iterator<Entry<String,ServiceSpace>> its = serviceSpaces.entrySet().iterator();
			while(its.hasNext()){
				Entry<String,ServiceSpace> entry = its.next();
				ServiceSpace serviceSpace = entry.getValue();
				ServiceHost host = serviceSpace.getServiceHosts().get(info.getHost());
				if(host==null){
					host = new ServiceHost();
					host.setHost(info.getHost());
					host.setCalled(info.getCalled());
					host.setUpdateTime(System.currentTimeMillis());
					host.setTimeOut(info.getTimeOut());
					host.setDoing(info.getDoing());
					host.setSleepTime(info.getSleepTime());
					host.setThreshold(info.getThreshold());
					serviceSpace.getServiceHosts().put(info.getHost(), host);
				}else{
					host.setCalled(info.getCalled());
					host.setUpdateTime(System.currentTimeMillis());
					host.setTimeOut(info.getTimeOut());
					host.setDoing(info.getDoing());
					host.setSleepTime(info.getSleepTime());
					host.setThreshold(info.getThreshold());
				}
			}
		}
	}
    
    /**
     * 将ServerInfo更新到注册服务器中
     * @param info
     */
    public void putServerInfo(ServerInfo info){
		synchronized(serviceRoot){
			ServiceSpace serviceSpace = serviceSpaces.get(info.getSpaceName());
			if(serviceSpace==null){
				serviceSpace = new ServiceSpace();
				serviceSpace.setName(info.getSpaceName());
				serviceSpaces.put(info.getSpaceName(), serviceSpace);
				ServiceHost host = new ServiceHost();
				host.setHost(info.getHost());
				host.setCalled(info.getCalled());
				host.setUpdateTime(System.currentTimeMillis());
				serviceSpace.getServiceHosts().put(info.getHost(), host);
				if(info.getServiceNames()!=null){
					for(String serviceName:info.getServiceNames()){
						Service service = new Service();
						service.setServiceName(serviceName);
						List<String> serviceHosts = new ArrayList<String>();
						serviceHosts.add(info.getHost());
						service.setServiceHosts(serviceHosts);
						serviceSpace.getServices().put(serviceName, service);
					}
				}
			}else{
				ServiceHost host = serviceSpace.getServiceHosts().get(info.getHost());
				if(host==null){
					host = new ServiceHost();
					host.setHost(info.getHost());
					host.setCalled(info.getCalled());
					host.setUpdateTime(System.currentTimeMillis());
					host.setTimeOut(info.getTimeOut());
					host.setDoing(info.getDoing());
					host.setSleepTime(info.getSleepTime());
					host.setThreshold(info.getThreshold());
					serviceSpace.getServiceHosts().put(info.getHost(), host);
				}else{
					host.setCalled(info.getCalled());
					host.setUpdateTime(System.currentTimeMillis());
					host.setTimeOut(info.getTimeOut());
					host.setDoing(info.getDoing());
					host.setSleepTime(info.getSleepTime());
					host.setThreshold(info.getThreshold());
				}
				if(info.getServiceNames()!=null){
					for(String serviceName:info.getServiceNames()){
						Service service = serviceSpace.getServices().get(serviceName);
						if(service==null){
							service = new Service();
							service.setServiceName(serviceName);
							List<String> serviceHosts = new ArrayList<String>();
							serviceHosts.add(info.getHost());
							service.setServiceHosts(serviceHosts);
							serviceSpace.getServices().put(serviceName, service);
						}else{
							for(int i=service.getServiceHosts().size()-1;i>=0;i--){
								if(service.getServiceHosts().get(i).equals(info.getHost())){
									service.getServiceHosts().remove(i);
									break;
								}
							}
//							int i;
//							for(i=service.getServiceHosts().size()-1;i>=0;i--){
//								if(serviceSpace.getServiceHosts().get(info.getHost()).getCalled()>
//								serviceSpace.getServiceHosts().get(service.getServiceHosts().get(i)).getCalled()){
//									service.getServiceHosts().add(i+1,info.getHost());
//									break;
//								}
//							}
//							if(i<0){
//								service.getServiceHosts().add(0,info.getHost());
//							}
							service.getServiceHosts().add(info.getHost());
						}
					}
				}
			}
		}
    }
    
	/**
	 * @see Object#toString()
	 */
	public String toString(){
		StringBuilder sb = new StringBuilder("serviceSpaces:");
		sb.append(serviceSpaces);
		return sb.toString();
	}
}
